﻿using IdentityModel;
using IdentityServer4;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using IdentityServer4.Models;
using IdentityServer4.Test;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using System.Text.Json;
using XLZF.MicroServices.ModelMigration;
using XLZF.MicroServices.Models;

namespace XLZF.MicroServices.AuthenticationCenter;

public class IdentityConfig
{
    /// <summary>
    /// OpenID
    /// </summary>
    /// <returns></returns>
    public static IEnumerable<IdentityResource> GetIdentityResources() => new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
    };

    /// <summary>
    /// 允许访问哪些Api（就像我允许我家里的哪些东西可以让顾客访问使用，如桌子，椅子等等）  
    /// </summary>
    /// <returns></returns>
    public static IEnumerable<ApiResource> GetApiResources() => new List<ApiResource>
    {
        new ApiResource("GetSearch", "用户获取API")
        {
            Scopes = {"scope1"}
        }
    };

    /// <summary>
    /// 作用域
    /// </summary>
    /// <returns></returns>
    public static IEnumerable<ApiScope> GetApiScopes() => new ApiScope[]
    {
        new ApiScope("scope1","作用域1"),
        new ApiScope("scope2","作用域2")
    };

    /// <summary>
    /// 允许哪些客户端访问
    /// </summary>
    /// <returns></returns>
    public static IEnumerable<Client> GetClients() => new[]
    {
        new Client
        {
            //客户端模式
            ClientId = "Harris_ClientID",//客户端唯一标识
            ClientName = "Harris_ClientName",//
            ClientSecrets = new []{new Secret("Harris123456".Sha256())},//
            AllowedGrantTypes= GrantTypes.ClientCredentials,
            AllowedScopes = new []{"scope1"}, //允许访问的资源
        },
        new Client
        {
            //资源拥有者模式
            ClientId = "Harris_Client_Pass_ID",
            ClientName="Harris_Client_Pass_Name",
            ClientSecrets = new []{new Secret("Harris123456".Sha256()) },//
            AllowedGrantTypes= GrantTypes.ResourceOwnerPassword,
            AllowedScopes = new []{"scope1"}, //允许访问的资源
        },
        new Client
        {
            //授权码模式
            ClientId = "Harris_MVC_ID",
            ClientName="Harris_MVC_Name",
            ClientSecrets = new []{new Secret("Harris123456".Sha256()) },//
            AllowedGrantTypes= GrantTypes.Code,//授权码模式
            RedirectUris = {"https://localhost:5001/signin-oidc"}, //登录
            PostLogoutRedirectUris={"https://localhost:5001/signout-callback-oidc"},//登出
            AllowAccessTokensViaBrowser=true,//允许将token通过浏览器传递
            RequireConsent=true,// 是否需要同意授权 （默认是false）
            RequirePkce=true,
            AllowedScopes = new []{ "scope1",IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile} //允许访问的资源
        }
    };

    /// <summary>
    /// 客户端下面的用户
    /// </summary>
    /// <returns></returns>
    public static List<TestUser> GetUsers() => new List<TestUser>()
    {
        new TestUser
        {
            SubjectId = "818727",
            Username = "alice",
            Password = "alice",
            Claims =
            {
                new Claim(JwtClaimTypes.Name, "Alice Smith"),
                new Claim(JwtClaimTypes.GivenName, "Alice"),
                new Claim(JwtClaimTypes.FamilyName, "Smith"),
                new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),
                new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                new Claim(JwtClaimTypes.WebSite, "http://alice.com"),
                new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(new
                {
                    street_address = "One Hacker Way",
                    locality = "Heidelberg",
                    postal_code = 69118,
                    country = "Germany"
                }), IdentityServerConstants.ClaimValueTypes.Json)
            },
            IsActive = true,
            ProviderName = "",
            ProviderSubjectId = ""
        },
        new TestUser
        {
            SubjectId = "88421113",
            Username = "bob",
            Password = "bob",
            Claims =
            {
                new Claim(JwtClaimTypes.Name, "Bob Smith"),
                new Claim(JwtClaimTypes.GivenName, "Bob"),
                new Claim(JwtClaimTypes.FamilyName, "Smith"),
                new Claim(JwtClaimTypes.Email, "BobSmith@email.com"),
                new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                new Claim(JwtClaimTypes.WebSite, "http://bob.com"),
                new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(new
                {
                    street_address = "One Hacker Way",
                    locality = "Heidelberg",
                    postal_code = 69118,
                    country = "Germany"
                }), IdentityServerConstants.ClaimValueTypes.Json)
            },
            IsActive = true,
            ProviderName = "",
            ProviderSubjectId = ""
        }
    };

    /// <summary>
    /// 读取Config中的数据同步到数据库表中
    /// </summary>
    /// <param name="app"></param>
    public static void InitializeDatabase(IApplicationBuilder app)
    {
        using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
        {
            serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
            var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
            var userContext = serviceScope.ServiceProvider.GetRequiredService<UserStoreDbContext>();
            userContext.Database.Migrate();
            context.Database.Migrate();

            #region 添加config中的客户端数据到数据库

            if (!context.Clients.Any())
            {
                foreach (var client in GetClients())
                {
                    //var lis = context.Clients.Where(p => p.ClientId == client.ClientId).ToList();

                    //if (lis.Count() == 0)
                    //{
                    context.Clients.Add(client.ToEntity());
                    //}
                }
                context.SaveChanges();
            }

            #endregion

            #region 添加config中的IdentityResources数据到数据库

            if (!context.IdentityResources.Any())
            {
                foreach (var resource in GetIdentityResources())
                {
                    context.IdentityResources.Add(resource.ToEntity());
                }
                context.SaveChanges();
            }
            #endregion

            #region 添加config中的ApiResources数据到数据库

            if (!context.ApiResources.Any())
            {
                foreach (var resource in GetApiResources())
                {
                    context.ApiResources.Add(resource.ToEntity());
                }
                context.SaveChanges();
            }
            #endregion

            #region 添加config中的apiscope（作用域)数据倒数据库

            if (!context.ApiScopes.Any())
            {
                foreach (var scope in GetApiScopes())
                {
                    context.ApiScopes.Add(scope.ToEntity());
                }
                context.SaveChanges();
            }

            #endregion

            #region 添加config中的Users数据到数据库

            if (!userContext.IdentityUser.Any())
            {
                int index = 0;
                foreach (var user in GetUsers())
                {
                    IdentityUser iuser = new IdentityUser()
                    {
                        IsActive = user.IsActive,
                        Password = user.Password,
                        ProviderName = user.ProviderName,
                        ProviderSubjectId = user.ProviderSubjectId,
                        SubjectId = user.SubjectId,
                        Username = user.Username,
                        IdentityUserClaims = user.Claims.Select(r => new IdentityUserClaim()
                        {
                            ClaimId = (index++).ToString(),

                            Name = r.Type,

                            Value = r.Value

                        }).ToList()
                    };
                    userContext.IdentityUser.Add(iuser);
                }
                userContext.SaveChanges();
            }

            #endregion
        }
    }


}